﻿using NationalInstruments.DAQmx;
using ScottPlot;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Channels;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using 低频天线阵列相控阵信号发生系统SmartFASK12.Models;
using Task = NationalInstruments.DAQmx.Task;

namespace 低频天线阵列相控阵信号发生系统SmartFASK12.Controls
{
    public class MNI
    {
        private Task _myTask; 
        private static MNI _instance = null;

        private MNI()
        {

        }

        public static MNI Singleton()
        {
            if (_instance == null)
            {
                _instance = new MNI();
            }
            return _instance;
        }

        /// <summary>
        /// 输出电压
        /// </summary>
        /// <param name="physicalChannel">物理通道1</param>
        /// <param name="Data">数据1</param>
        /// <param name="physicalChannel2">物理通道2</param>
        /// <param name="Data2">数据2</param>
        /// <param name="minimumValue">最小值</param>
        /// <param name="maximumValue">最大值</param>
        /// <param name="rate">采样率</param>
        /// <param name="samplesPerChannel">采样数量</param>
        /// <returns></returns>
        public string OutputOoltage(string physicalChannel, double[] Data, string physicalChannel2, double[] Data2, double minimumValue, double maximumValue, double rate, int samplesPerChannel)
        {
            try
            {
                if (!string.IsNullOrEmpty(physicalChannel2))
                {
                    physicalChannel += "," + physicalChannel2;
                }
                // Create the task and channel
                _myTask = new Task();
                _myTask.AOChannels.CreateVoltageChannel(physicalChannel,
                    "",
                    minimumValue,
                    maximumValue,
                    AOVoltageUnits.Volts);

                // Verify the task before doing the waveform calculations
                _myTask.Control(TaskAction.Verify);

                // Configure the sample clock with the calculated rate and 
                _myTask.Timing.SampleClockRate = rate;

                // 设置超时时间为100秒
                //myTask.Stream.Timeout = 100000;

                // specified clock source
                _myTask.Timing.ConfigureSampleClock(System.String.Empty,
                    rate,
                    SampleClockActiveEdge.Rising,
                    SampleQuantityMode.ContinuousSamples,
                    samplesPerChannel);

                if (Data2 != null)
                {
                    AnalogMultiChannelWriter writer = new AnalogMultiChannelWriter(_myTask.Stream);
                    // 设置数据写入缓冲区
                    double[,] data = new double[2, Data.Length];
                    for (int i = 0; i < Data.Length; i++)
                    {
                        data[0, i] = Data[i];
                        data[1, i] = Data2[i];
                    }
                    // 将数据写入缓冲区
                    writer.WriteMultiSample(false, data);
                }
                else
                {
                    AnalogSingleChannelWriter writer =
                        new AnalogSingleChannelWriter(_myTask.Stream);

                    writer.WriteMultiSample(false, Data);//fGen.Data
                }


                _myTask.Done += new TaskDoneEventHandler(myTask_Done);
                // Start writing data
                _myTask.Start();

                // Update UI
            }
            catch (DaqException ex)
            {
                //Log.Error(ex, ex.Message);
                _myTask.Dispose();
                return ex.Message;
            }

            System.Windows.Forms.Cursor.Current = Cursors.Default;
            return null;
        }

        /// <summary>
        /// 采集电压
        /// </summary>
        /// <param name="physicalChannelName">物理通道</param>
        /// <param name="minimumValue">最小值</param>
        /// <param name="maximumValue">最大值</param>
        /// <param name="rate">采样率</param>
        /// <param name="samplesPerChannel">采样数量</param>
        /// <returns></returns>
        public double[] CollectVoltage(string physicalChannelName,double minimumValue,double maximumValue,double rate, int samplesPerChannel, AITerminalConfiguration aITerminalConfiguration = AITerminalConfiguration.Rse)
        {
            try
            {
                //创建采集任务
                using (NationalInstruments.DAQmx.Task myTask = new NationalInstruments.DAQmx.Task())
                {
                    // 创建虚拟通道
                    myTask.AIChannels.CreateVoltageChannel(physicalChannelName, // 物理通道
                                                        "",//物理通道的名称
                                                        aITerminalConfiguration,//(AITerminalConfiguration)(-1), // -1表示使用缺省值
                                                        minimumValue, // 最小值
                                                        maximumValue,  // 最大值
                                                        AIVoltageUnits.Volts); // 配置时域参数   

                    myTask.Timing.ConfigureSampleClock(System.String.Empty,//外部时钟源线或使用“”作为内部时钟
                                                       rate, // 外部时钟的预期速率或内部时钟的实际速率
                                                       SampleClockActiveEdge.Rising, //上升或下降边缘获取
                                                       SampleQuantityMode.ContinuousSamples, // 连续或有限样本
                                                       samplesPerChannel);// 要获取或用于缓冲区大小（如果连续）的有限样本数
                    // 校验任务
                    myTask.Control(TaskAction.Verify);

                    // 设置超时时间为100秒
                    myTask.Stream.Timeout = MPublic.ConfigModel.timeout * 1000;

                    //多通道读取器，从任务中的一个或多个模拟输入通道读取样本       
                    AnalogMultiChannelReader myAnalogReader = new AnalogMultiChannelReader(myTask.Stream);

                    DateTime t1 = DateTime.Now;

                    double[,] dd = myAnalogReader.ReadMultiSample(samplesPerChannel);

                    TimeSpan ts = DateTime.Now - t1;

                    double ms = ts.TotalMilliseconds;

                    if (dd != null && dd.Length > 0)
                    {
                        double[] res = new double[samplesPerChannel];
                        for (int i = 0; i < samplesPerChannel; i++)
                        {
                            res[i] = dd[0, i];
                        }
                        return res;
                    }
                }
            }
            catch (Exception ex)
            {
                //Log.Error(ex, ex.Message);
            }
            return null;
        }

        /// <summary>
        /// 采集电压-9174
        /// </summary>
        /// <param name="physicalChannelName">物理通道</param>
        /// <param name="minimumValue">最小值</param>
        /// <param name="maximumValue">最大值</param>
        /// <param name="rate">采样率</param>
        /// <param name="samplesPerChannel">采样数量</param>
        /// <returns></returns>
        public double[,] CollectVoltage_9174(string physicalChannelName, double minimumValue, double maximumValue, double rate, int samplesPerChannel, AITerminalConfiguration aITerminalConfiguration = AITerminalConfiguration.Rse)
        {
            try
            {
                // 创建采集任务
                using (Task myTask = new Task())
                {
                    // 创建虚拟通道
                    myTask.AIChannels.CreateVoltageChannel(physicalChannelName,
                                                           "",
                                                           aITerminalConfiguration,
                                                           minimumValue,
                                                           maximumValue,
                                                           AIVoltageUnits.Volts);

                    // 配置时域参数
                    myTask.Timing.ConfigureSampleClock("", rate, SampleClockActiveEdge.Rising,
                        SampleQuantityMode.FiniteSamples, samplesPerChannel);

                    // 校验任务
                    myTask.Control(TaskAction.Verify);

                    // 设置超时时间为100秒
                    myTask.Stream.Timeout = 10000;

                    AnalogMultiChannelReader myAnalogReader = new AnalogMultiChannelReader(myTask.Stream);

                    //从通道读取数据
                    double[,] data = myAnalogReader.ReadMultiSample(samplesPerChannel);
                    // 读取数据
                    //for (int i = 0; i < samplesPerChannel; i++)
                    //{
                    //    //this.Context.Variants["电压测量/电压"].Value = data.Length > 0 ? data[0] : 0;
                    //}
                    return data;
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, ex.Message);
            }
            return null;
        }

        /// <summary>
        /// 采集电压
        /// </summary>
        /// <param name="physicalChannelName">物理通道</param>
        /// <param name="minimumValue">最小值</param>
        /// <param name="maximumValue">最大值</param>
        /// <param name="rate">采样率</param>
        /// <param name="samplesPerChannel">采样数量</param>
        /// <returns></returns>
        public double[,] CollectVoltage_4431(string physicalChannelName, double minimumValue, double maximumValue, double rate, int samplesPerChannel, AITerminalConfiguration aITerminalConfiguration = AITerminalConfiguration.Rse)
        {
            try
            {
                //创建采集任务
                using (NationalInstruments.DAQmx.Task myTask = new NationalInstruments.DAQmx.Task())
                {
                    // 创建虚拟通道
                    myTask.AIChannels.CreateVoltageChannel(physicalChannelName, // 物理通道
                                                        "",//物理通道的名称
                                                        aITerminalConfiguration,//(AITerminalConfiguration)(-1), // -1表示使用缺省值
                                                        minimumValue, // 最小值
                                                        maximumValue,  // 最大值
                                                        AIVoltageUnits.Volts); // 配置时域参数

                    myTask.Timing.ConfigureSampleClock(System.String.Empty,//外部时钟源线或使用“”作为内部时钟
                                                       rate, // 外部时钟的预期速率或内部时钟的实际速率
                                                       SampleClockActiveEdge.Rising, //上升或下降边缘获取
                                                       SampleQuantityMode.ContinuousSamples, // 连续或有限样本
                                                       samplesPerChannel);// 要获取或用于缓冲区大小（如果连续）的有限样本数

                    // 设置超时时间为100秒
                    myTask.Stream.Timeout = MPublic.ConfigModel.timeout * 1000;

                    // 校验任务
                    myTask.Control(TaskAction.Verify);

                    //多通道读取器，从任务中的一个或多个模拟输入通道读取样本       
                    AnalogMultiChannelReader myAnalogReader = new AnalogMultiChannelReader(myTask.Stream);
                    
                    //DateTime t1 = DateTime.Now;
                    double[,] dd = myAnalogReader.ReadMultiSample(samplesPerChannel);
                    return dd;
                    //TimeSpan ts = DateTime.Now - t1;

                    //double ms = ts.TotalMilliseconds;

                    //if (dd != null && dd.Length > 0)
                    //{
                    //    double[] res = new double[samplesPerChannel];
                    //    for (int i = 0; i < samplesPerChannel; i++)
                    //    {
                    //        res[i] = dd[0, i];
                    //    }
                    //    return res;
                    //}
                }
            }
            catch (Exception ex)
            {
                //Log.Error(ex, ex.Message);
            }
            return null;
        }

        /// <summary>
        /// 获取通道
        /// </summary>
        /// <returns></returns>
        public string[] GetChannals(PhysicalChannelTypes physicalChannelTypes)
        {
            try
            {
                return DaqSystem.Local.GetPhysicalChannels(physicalChannelTypes, PhysicalChannelAccess.External);
            }
            catch (Exception ex)
            {
                //Log.Error(ex.Message, ex);
            }

            return null;
        }

        /// <summary>
        /// 电压输出任务完成
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void myTask_Done(object sender, TaskDoneEventArgs e)
        {
            if (_myTask != null)
            {
                _myTask.Stop();
                _myTask.Dispose();
            }

            //MEvent.Singleton().EmitVoltageOutputCompleted();
        }

        /// <summary>
        /// 输出电压停止
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void Stop()
        {
            if (_myTask != null)
            {
                _myTask.Stop();
                _myTask.Dispose();
            }
        }
    }
}
